package org.deltaset.desktop;

import java.util.List;
import java.util.Map;
import javax.faces.application.ViewHandler;
import javax.annotation.ManagedBean;

import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import org.deltaset.faces.FacesUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Scope;
import org.springframework.web.context.WebApplicationContext;

/**
 *
 * @author dmakariev
 */
@ManagedBean("desktopBean")
@Scope(WebApplicationContext.SCOPE_REQUEST)
public class DesktopBean implements ApplicationContextAware{

    private final static String CONTEXT_KEY = "DesktopContext_" + DesktopBean.class.getName();
    //TODO: parameter from component    
    private String defaultAppSrc;// = "/home.xhtml";   
    private DesktopHandler desktopHandler;       

    public DesktopBean getDesktop() {
        return this;
    }

    public MenuItem getMenuItem() {
        return getDesktopContext().getCurrentMenuItem();
    }

    public void setMenuItem(MenuItem menuItem) {
        getDesktopContext().setCurrentMenuItem(menuItem);
        this.setPageSrc(menuItem.getTemplateSrc());
        if (menuItem.isRefreshable()) {
            refreshViewState();
        }
    }

//    public void setMenuItem(MenuItem menuItem, String src) {
//        getDesktopContext().setCurrentMenuItem(menuItem);
//        this.setPageSrc(src);
//        refreshViewState();
//    }
    //use only where it is REALLY necessary. makes the response relatively 30 - 40% slower ! 
    //with more complex models the difference gets smaller.(1%-12%)
    private void refreshViewState() {
        final FacesContext facesContext = FacesContext.getCurrentInstance();
        final String viewId = facesContext.getViewRoot().getViewId();
        final ViewHandler handler = facesContext.getApplication().getViewHandler();
        final UIViewRoot root = handler.createView(facesContext, viewId);
        root.setViewId(viewId);
        facesContext.setViewRoot(root);
    }

    public List<MenuGroup> getMenuGroups() {
        return getCurrentApp().getMenuGroups();
    }

    public String getAppTitle() {
        return getCurrentApp().getAppTitle();
    }

    public String getAppId() {
        return getCurrentApp().getAppId();
    }

    public AppItem getCurrentApp() {
        return getDesktopContext().getCurrentApp();
    }

    public String prepareApp(AppItem currentApp) {
        final String appSrc = currentApp.getAppSrc();
        final String output = (null == appSrc) ? getDefaultAppSrc() : appSrc;
        getDesktopContext().setCurrentApp(currentApp);
        this.setMenuItem(currentApp.getDefaultMenuItem());
        return output + "?faces-redirect=true";
    }

    public List<AppItem> getTopMenu() {
        return getDesktopHandler().getTopMenu();
    }

    public String getPageSrc() {
        return getDesktopContext().getPageSrc();
    }

    public void setPageSrc(String pageSrc) {
        this.getDesktopContext().setPageSrc(pageSrc);
    }

    private String getDefaultAppSrc() {
        if (null == defaultAppSrc) {
            this.defaultAppSrc = getTopMenuProvider().getDefaultSrc();
        }
        return defaultAppSrc;
    }
  

    private TopMenuProvider getTopMenuProvider() {
        final TopMenuProvider topMenuProvider = this.applicationContext.getBean(TopMenuProvider.class);      
        return topMenuProvider;
    }

    private DesktopHandler getDesktopHandler() {
        if (null == desktopHandler) {
            this.desktopHandler = new DesktopHandler(getTopMenuProvider());
        }
        return desktopHandler;
    }

    private DesktopContext getDesktopContext() {
        final Map<String, Object> session = FacesUtils.getSessionMap();
        if (!session.containsKey(CONTEXT_KEY)) {
            final DesktopContext dc = getDesktopHandler().getDefaultDesktopContext();
            session.put(CONTEXT_KEY, dc);
        }
        final DesktopContext dc = (DesktopContext) session.get(CONTEXT_KEY);
        if (null == dc) {
            throw new IllegalStateException("ERROR " + CONTEXT_KEY + " cannot be NULL!");
        }
        return dc;
    }

    private ApplicationContext applicationContext;
    
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
    
     private <T> T getSpringBean(Class<T> beayType) {
        try {
            return this.applicationContext.getBean(beayType);
        } catch (BeansException ex) {
            return null;
        }
    }
}
